import pyhyperscan

class PatternMatcher:
    def __del__(self):
        # 释放数据库
        if hasattr(self, 'db') and self.db:
            pyhyperscan.free_database(self.db)

    @staticmethod
    def safe_byte_offset_to_char_offset(s, byte_offset):
        encoded = s.encode('utf-8')
        while byte_offset > 0:
            try:
                return len(encoded[:byte_offset].decode('utf-8'))
            except UnicodeDecodeError:
                byte_offset -= 1  # 回退到上一个完整字符
        return 0

    def __init__(self, patterns):
        self.text = None
        self.patterns = patterns
        self.patterns_ids = list(range(len(patterns)))  # 为每个模式分配唯一ID
        self.matches = []  # 存储匹配结果

        # 检查模式有效性
        ret, msg = pyhyperscan.check_patterns(patterns, [pyhyperscan.HS_FLAG_DOTALL_PY | pyhyperscan.HS_FLAG_SOM_LEFTMOST_PY] * len(patterns))
        if not ret:
            raise ValueError(f"Invalid patterns: {msg}")

        # 编译多模式数据库
        flags = [pyhyperscan.HS_FLAG_DOTALL_PY | pyhyperscan.HS_FLAG_SOM_LEFTMOST_PY] * len(patterns)
        self.db = pyhyperscan.compile_multi_patterns(patterns, flags, self.patterns_ids)

    def on_match(self, id, from_, to, flags):
        """匹配回调函数，存储结果到列表"""
        from_ = self.safe_byte_offset_to_char_offset(self.text, from_)
        to = self.safe_byte_offset_to_char_offset(self.text, to)
        self.matches.append({
            'id': id,
            'pattern': self.patterns[id],  # 通过ID获取原始模式
            'start': from_,
            'end': to,
            'match': self.text[from_:to]  # 提取匹配文本
        })

    def match_all(self, scan_text: str):
        """扫描文本并返回所有匹配结果"""
        self.matches = []  # 清空旧结果
        self.text = scan_text    # 存储文本供回调函数使用
        pyhyperscan.scan_data(self.db, self.text, self.on_match)
        return self.matches


if __name__ == '__main__':
    # 示例用法
    patterns = ['123', '男|女']  # Hyperscan需要字节模式（bytes）
    matcher = PatternMatcher(patterns)

    text = 'hello wo男rld123女'
    print(f"len text: {len(text)}")
    results = matcher.match_all(text)
    print(f"results: {results}")
    # 打印匹配结果
    for match in results:
        print(f"匹配到模式 ID={match['id']} {match['pattern']}")
